package com.ruoyi.common.sql;

public class SelectQuery  extends Query{
    private boolean distinct;

    private SelectQuery() {}

    public static Builder builder() {
        return new Builder(new SelectQuery());
    }

    @Override
    public String build() {
        StringBuilder sql = new StringBuilder("SELECT ");

        if (distinct) {
            sql.append("DISTINCT ");
        }

        if (columns.isEmpty()) {
            sql.append("*");
        } else {
            sql.append(String.join(", ", columns));
        }

        sql.append(" FROM ");
        buildTables(sql);

        if (where != null) {
            sql.append(" WHERE ");
            where.build(sql);
        }

        if (groupBy != null) {
            groupBy.build(sql);
        }

        if (having != null) {
            having.build(sql);
        }

        if (!orderBys.isEmpty()) {
            sql.append(" ORDER BY ");
            for (int i = 0; i < orderBys.size(); i++) {
                if (i > 0) sql.append(", ");
                orderBys.get(i).build(sql);
            }
        }

        if (limit != null) {
            sql.append(" LIMIT ").append(limit);
        }

        if (offset != null) {
            sql.append(" OFFSET ").append(offset);
        }

        return sql.toString();
    }

    private void buildTables(StringBuilder sql) {
        for (int i = 0; i < tables.size(); i++) {
            Table table = tables.get(i);
            if (i > 0) {
                sql.append(" ").append(table.getJoinType().getCode()).append(" JOIN ");
            }
            table.build(sql);
        }
    }

    public static class Builder extends Query.Builder<Builder> {
        private Builder(SelectQuery query) {
            super(query);
        }

        public Builder distinct() {
            ((SelectQuery) query).distinct = true;
            return this;
        }

        @Override
        protected Builder self() {
            return this;
        }

        @Override
        public SelectQuery build() {
            return (SelectQuery) query;
        }
    }
}